home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / crypt / idea.lha / idea.c < prev    next >
C/C++ Source or Header  |  1992-08-27  |  21KB  |  760 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "crypt.h"
  4.  
  5. #define TRUE                 1 /* boolean constant for true                   */
  6. #define FALSE                0 /* boolean constant for false                  */
  7.  
  8. #define nomode               0 /* no mode is specified                        */
  9. #define ecb                  1 /* electronic code book mode                   */
  10. #define cbc                  2 /* cipher block chaining mode                  */
  11. #define cfb                  3 /* ciphertext feedback mode                    */
  12. #define ofb                  4 /* output feedback mode                        */
  13. #define tan                  5 /* tandem DM-scheme for hashing                */
  14. #define abr                  6 /* abreast DM-scheme for hashing               */
  15. #define error               -1 /* error constant                              */
  16. #define eol                 -2 /* end of line                                 */
  17. #define colon               -3 /* character ':'                               */
  18. #define maxInterleave     1024 /* maximal interleave factor + 1               */
  19. #define nofChar ('~' - '!' + 1) /* number of different printable characters   */
  20. #define maxBufLen  (dataSize * 1024) /* size of input and output buffer       */
  21.  
  22. userkey_t(userKey) ;            /* user selected 128 bit key                   */
  23. key_t(key) ;                    /* expanded key with 832 bits                  */
  24. data_t(state[maxInterleave]) ;  /* state informations for interleaving modes   */
  25. data_t(hashLow) ;               /* lower 64 bits of hash value                 */
  26. data_t(hashHigh) ;              /* higher 64 bits of hash value                */
  27.  
  28. u_int32 inputLen    = 0;       /* current number of bytes read from 'inFile'  */
  29. int interleave      = 0;       /* current interleave factor                   */
  30. int time            = 0;       /* time for interleaving modes                 */
  31. int time_N          = 0;       /* time-interleave for interleaving modes      */
  32. int mode            = nomode;  /* current mode                                */
  33.  
  34. int optEncrypt      = FALSE;   /* encrypt option 'e'                          */
  35. int optDecrypt      = FALSE;   /* decrypt option 'd'                          */
  36. int optHash         = FALSE;   /* hash option 'h'                             */
  37. int optCopyHash     = FALSE;   /* copy and hash option 'H'                    */
  38. int optKeyHexString = FALSE;   /* key as hex-string option 'K'                */
  39. int optKeyString    = FALSE;   /* key as string option 'k'                    */
  40.  
  41. int inBufLen        = maxBufLen; /* current length of data in 'inBuf'         */
  42. int inBufPos        = maxBufLen; /* current read position of 'inBuf'          */
  43. int outBufLen       = 0;       /* current write position of 'outBuf'          */
  44. u_int8 inBuf[maxBufLen];       /* buffer for file read                        */
  45. u_int8 outBuf[maxBufLen];      /* buffer for file write                       */
  46.  
  47. FILE *inFile;                  /* file with input data (plain or ciphertext)  */
  48. FILE *outFile;                 /* file for output data (plain or ciphertext)  */
  49. FILE *hashFile;                /* 128 bit hash value is written to this file  */
  50.  
  51.  
  52. /******************************************************************************/
  53. /* initialize global variables                                                */
  54.  
  55. void Init()
  56.  
  57. {    int i, pos;
  58.  
  59.     for (i = 0; i < userKeyLen; i++)
  60.         userKey[i] = 0;
  61.     for (pos = 0; pos < maxInterleave; pos++) {
  62.         for (i = 0; i < dataLen; i++)
  63.             state[pos][i] = 0;
  64.     }
  65. }    /* Init */
  66.  
  67. /******************************************************************************/
  68. /*                          E R R O R - H A N D L I N G                       */
  69. /******************************************************************************/
  70. /* write usage error message and terminate program                            */
  71.  
  72. void UsageError(int num)
  73.  
  74. {
  75. fprintf(stderr, "Usage Error %d\n\
  76. Usage:   idea [ -e | -d ] [ -ecb | -cbcN | -cfbN | -ofbN ]       \n\
  77.               ( -k keyString | -K keyHexString )                 \n\
  78.               [ inputFile [ outputFile ] ]                       \n\
  79.          idea [ -h | -H ] [ -tan | -abr ]                        \n\
  80.               [ -k keyString | -K keyHexString ]                 \n\
  81.               [ inputFile [ [ outputFile ] hashvalFile ] ]       \n\
  82. \nExample: idea -Hk \"k e y\" infile | idea -cbc8 -K 123:9a::eF - outfile\n\
  83. \n");
  84. exit(5);
  85. } /* UsageError */
  86.  
  87. /******************************************************************************/
  88. /* write error message and terminate program                                  */
  89.  
  90. void Error(int num, char *str)
  91.  
  92. {    fprintf(stderr, "ERROR %d in idea: %s\n", num, str); exit(10); } /* Error */
  93.  
  94. /******************************************************************************/
  95. /* write system error message and terminate program                           */
  96.  
  97. void PError(char *str)
  98.  
  99. {    perror(str); exit(20); } /* PError */
  100.  
  101. /******************************************************************************/
  102. /*                          D E C R Y P T I O N  /  E N C R Y P T I O N       */
  103. /******************************************************************************/
  104. /* read one data-block from 'inFile'                                          */
  105.  
  106. int GetData(data_t(data))
  107.  
  108. {    register int i, len;
  109.     register u_int16 h;
  110.     register u_int8 *inPtr;
  111.  
  112.     if (inBufPos >= inBufLen) {
  113.         if (inBufLen != maxBufLen) return 0;
  114.         inBufLen = fread(inBuf, 1, maxBufLen, inFile);
  115.         inBufPos = 0;
  116.         if (inBufLen == 0) return 0;
  117.         if (inBufLen % dataSize != 0)
  118.             for (i = inBufLen; i % dataSize != 0; i++)
  119.                 inBuf[i] = 0;
  120.     }
  121.     inPtr = &inBuf[inBufPos];
  122.     for (i = 0; i < dataLen; i++) {
  123.         h = ((u_int16)(*inPtr++) & 0xFF) << 8;
  124.         data[i] = h | ((u_int16)(*inPtr++) & 0xFF);
  125.     }
  126.     inBufPos += dataSize;
  127.     if (inBufPos <= inBufLen)
  128.         len = dataSize;
  129.     else
  130.         len = inBufLen + dataSize - inBufPos;
  131.     inputLen += len;
  132.     return len;
  133. } /* GetData */
  134.  
  135. /******************************************************************************/
  136. /* write one data-block to 'outFile'                                          */
  137.  
  138. void PutData(data_t(data), int len)
  139.  
  140. {    register int i;
  141.     register u_int16 h;
  142.     register u_int8 *outPtr;
  143.  
  144.     outPtr = &outBuf[outBufLen];
  145.     for (i = 0; i < dataLen; i++) {
  146.         h = data[i];
  147.         *(outPtr++) = (h >> 8) & 0xFF;
  148.         *(outPtr++) = h & 0xFF;
  149.     }
  150.     outBufLen += len;
  151.     if (outBufLen >= maxBufLen) {
  152.         fwrite(outBuf, 1, maxBufLen, outFile);
  153.         outBufLen = 0;
  154.     }
  155. } /* PutData */
  156.  
  157. /******************************************************************************/
  158. /* write last block to 'outFile' and close 'outFile'                          */
  159.  
  160. void CloseOutput()
  161.  
  162. {    if (outBufLen > 0) {
  163.         fwrite(outBuf, 1, outBufLen, outFile);
  164.         outBufLen = 0;
  165.     }
  166.     close(outFile);
  167. } /* CloseOutput */
  168.  
  169. /******************************************************************************/
  170. /* increment time and time_N                                                  */
  171.  
  172. void IncTime()
  173. {    time = (time + 1) % maxInterleave;
  174.     time_N = (time_N + 1) % maxInterleave;
  175. } /* IncTime */
  176.  
  177. /******************************************************************************/
  178. /* encrypt one data-block                                                     */
  179.  
  180. void EncryptData(data_t(data))
  181.  
  182. {    int i;
  183.  
  184.     switch (mode) {
  185.         case ecb:
  186.             Idea(data, data, key);
  187.             break;
  188.         case cbc:
  189.             for (i = dataLen - 1; i >= 0; i--)
  190.                 data[i] ^= state[time_N][i];
  191.             Idea(data, data, key);
  192.             for (i = dataLen - 1; i >= 0; i--)
  193.                 state[time][i] = data[i];
  194.             IncTime();
  195.             break;
  196.         case cfb:
  197.             Idea(state[time_N], state[time], key);
  198.             for (i = dataLen - 1; i >= 0; i--)
  199.                 data[i] = state[time][i] ^= data[i];
  200.             IncTime();
  201.             break;
  202.         case ofb:
  203.             Idea(state[time_N], state[time], key);
  204.             for (i = dataLen - 1; i >= 0; i--)
  205.                 data[i] ^= state[time][i];
  206.             IncTime();
  207.             break;
  208.         default: break;
  209.     }
  210. } /* EncryptData */
  211.  
  212. /******************************************************************************/
  213. /* decrypt one data-block                                                     */
  214.  
  215. void DecryptData(data_t(data))
  216.  
  217. {    int i;
  218.  
  219.     switch (mode) {
  220.         case ecb:
  221.             Idea(data, data, key);
  222.             break;
  223.         case cbc:
  224.             for (i = dataLen - 1; i >= 0; i--)
  225.                 state[time][i] = data[i];
  226.             Idea(data, data, key);
  227.             for (i = dataLen - 1; i >= 0; i--)
  228.                 data[i] ^= state[time_N][i];
  229.             IncTime();
  230.             break;
  231.         case cfb:
  232.             for (i = dataLen - 1; i >= 0; i--)
  233.                 state[time][i] = data[i];
  234.             Idea(state[time_N], data, key);
  235.             for (i = dataLen - 1; i >= 0; i--)
  236.                 data[i] ^= state[time][i];
  237.             IncTime();
  238.             break;
  239.         case ofb:
  240.             Idea(state[time_N], state[time], key);
  241.             for (i = dataLen - 1; i >= 0; i--)
  242.                 data[i] ^= state[time][i];
  243.             IncTime();
  244.             break;
  245.         default: break;
  246.     }
  247. } /* DecryptData */
  248.  
  249. /******************************************************************************/
  250. /* hash one data-block                                                        */
  251.  
  252. void HashData(data_t(data))
  253.  
  254. {    int i;
  255.     userkey_t(userKey);
  256.     key_t(key);
  257.     data_t(w);
  258.  
  259.     for (i = dataLen - 1; i >= 0; i--) {
  260.         userKey[i] = hashLow[i];
  261.         userKey[i + dataLen] = data[i];
  262.     }
  263.     ExpandUserKey(userKey, key);
  264.     Idea(hashHigh, w, key);
  265.     if (mode == abr) {
  266.         for (i = dataLen - 1; i >= 0; i--) {
  267.             userKey[i] = data[i];
  268.             userKey[i + dataLen] = hashHigh[i];
  269.             hashHigh[i] ^= w[i];
  270.             w[i] = ~ hashLow[i];
  271.         }
  272.     }
  273.     else { /* mode == tan */
  274.         for (i = dataLen - 1; i >= 0; i--) {
  275.             hashHigh[i] ^= w[i];
  276.             userKey[i] = data[i];
  277.             userKey[i + dataLen] = w[i];
  278.             w[i] = hashLow[i];
  279.         }
  280.     }
  281.     ExpandUserKey(userKey, key);
  282.     Idea(w, w, key);
  283.     for (i = dataLen - 1; i >= 0; i--)
  284.         hashLow[i] ^= w[i];
  285. } /* HashData */
  286.  
  287. /******************************************************************************/
  288. /* write value of a 16-bit unsigned integer in hex format to 'hashFile'       */
  289.  
  290. void WriteHex(u_int16 val)
  291.  
  292. {    char str[8];
  293.     int i;
  294.  
  295.     sprintf(str, "%4X", val);
  296.     for (i = 0; i < 4; i++)
  297.         if (str[i] == ' ')
  298.             str[i] = '0';
  299.     fprintf(hashFile, "%s", str);
  300. } /* WriteHex */
  301.  
  302. /******************************************************************************/
  303. /* write the hash value to 'hashFile'                                         */
  304.  
  305. void WriteHashValue()
  306.  
  307. {    int i;
  308.  
  309.     for (i = 0; i < dataLen; i++) WriteHex(hashHigh[i]);
  310.     for (i = 0; i < dataLen; i++) WriteHex(hashLow[i]);
  311. } /* WriteHashValue */
  312.  
  313. /******************************************************************************/
  314. /* store integer 'value' in 'data'                                            */
  315.  
  316. void PlainLenToData(u_int32 value, data_t(data))
  317.  
  318. {    data[3] = (u_int16)((value << 3) & 0xFFFF);
  319.     data[2] = (u_int16)((value >> 13) & 0xFFFF);
  320.     data[1] = (u_int16)((value >> 29) & 0x0007);
  321.     data[0] = 0;
  322. } /* PlainLenToData */
  323.  
  324. /******************************************************************************/
  325. /* extract integer 'value' from 'data'                                        */
  326.  
  327. void data_toPlainLen(data_t(data), u_int32 *value)
  328.  
  329. {    if ((data[0] != 0) || (data[1] > 7) || ((data[3] & 7) != 0))
  330.         Error(1, "input is not a valid cryptogram");
  331.     *value = ((u_int32)(data[3]) >> 3) & 0x1FFF |
  332.         ((u_int32)(data[2]) << 13) |
  333.         ((u_int32)(data[1]) << 29);
  334. } /* data_toPlainLen */
  335.  
  336. /******************************************************************************/
  337. /* encrypt / decrypt complete data-stream or compute hash value of data-stream*/
  338.  
  339. void CryptData()
  340.  
  341. {    int t, i;
  342.     u_int32 len;
  343.     data_t(dat[4]);
  344.     data_t(data);
  345.  
  346.     if (optEncrypt) { /* encrypt data */
  347.         while ((len = GetData(data)) == dataSize) {
  348.             EncryptData(data);
  349.             PutData(data, dataSize);
  350.         }
  351.         if (len > 0) {
  352.             EncryptData(data);
  353.             PutData(data, dataSize);
  354.         }
  355.         PlainLenToData(inputLen, data);
  356.         EncryptData(data);
  357.         PutData(data, dataSize);
  358.         CloseOutput();
  359.     }
  360.     else if (optDecrypt) { /* decrypt data */
  361.         if ((len = GetData(dat[0])) != dataSize) {
  362.             if (len != 0)
  363.                 Error(2, "input is not a valid cryptogram");
  364.             else
  365.                 Error(3, "there are no data to decrypt");
  366.         }
  367.         DecryptData(dat[0]);
  368.         if ((len = GetData(dat[1])) != dataSize) {
  369.             if (len != 0)
  370.                 Error(4, "input is not a valid cryptogram");
  371.             data_toPlainLen(dat[0], &len);
  372.             if (len != 0)
  373.                 Error(5, "input is not a valid cryptogram");
  374.         }
  375.         else {
  376.             DecryptData(dat[1]);
  377.             t = 2;
  378.             while ((len = GetData(dat[t])) == dataSize) {
  379.                 DecryptData(dat[t]);
  380.                 PutData(dat[(t + 2) & 3], dataSize);
  381.                 t = (t + 1) & 3;
  382.             }
  383.             if (len != 0)
  384.                 Error(6, "input is not a valid cryptogram");
  385.             data_toPlainLen(dat[(t + 3) & 3], &len);
  386.             len += 2 * dataSize;
  387.             if ((inputLen < len) && (len <= inputLen + dataSize)) {
  388.                 len -= inputLen;
  389.                 PutData(dat[(t + 2) & 3], len);
  390.             }
  391.             else
  392.                 Error(7, "input is not a valid cryptogram");
  393.         }
  394.         CloseOutput();
  395.     }
  396.     else { /* compute hash value */
  397.         for (i = dataLen - 1; i >= 0; i--) {
  398.             hashHigh[i] = userKey[i];
  399.             hashLow[i] = userKey[i + dataLen];
  400.         }
  401.         if (optCopyHash) {
  402.             while ((len = GetData(data)) == dataSize) {
  403.                 HashData(data);
  404.                 PutData(data, dataSize);
  405.             }
  406.             if (len > 0) {
  407.                 HashData(data);
  408.                 PutData(data, len);
  409.             }
  410.             PlainLenToData(inputLen, data);
  411.             HashData(data);
  412.             CloseOutput();
  413.         }
  414.         else { /* optHash */
  415.             while ((len = GetData(data)) == dataSize)
  416.                 HashData(data); 
  417.             if (len > 0)
  418.                 HashData(data);
  419.             PlainLenToData(inputLen, data);
  420.             HashData(data);
  421.         }
  422.         WriteHashValue();
  423.     }
  424. } /* CryptData */
  425.  
  426.  
  427. /******************************************************************************/
  428. /*                          I N I T I A L I Z A T I O N                       */
  429. /******************************************************************************/
  430. /* set option to TRUE                                                         */
  431.  
  432. void SetOption(int *option)
  433.  
  434. {    if (*option)
  435.         UsageError(8);
  436.     *option = TRUE;
  437. } /* SetOption */
  438.  
  439. /******************************************************************************/
  440. /* set encryption / decryption mode                                           */
  441.  
  442. void SetMode(int newMode, char **str)
  443.  
  444. {    if (mode != nomode)
  445.         UsageError(9);
  446.     mode = newMode;
  447.     (*str)++;
  448.     (*str)++;
  449.     if ((newMode == cbc) || (newMode == cfb) || (newMode == ofb)) {
  450.         if (('0' <= **str) && (**str <= '9')) {
  451.             interleave = 0;
  452.             do {
  453.                 interleave = 10 * interleave + (**str - '0');
  454.                 if (interleave >= maxInterleave)
  455.                     Error(10, "interleave factor is too large");
  456.                 (*str)++;
  457.             } while (('0' <= **str) && (**str <= '9'));
  458.             if (interleave == 0)
  459.                 Error(11, "interleave factor is zero");
  460.         }
  461.         else interleave = 1;
  462.     }
  463. } /* SetMode */
  464.  
  465. /******************************************************************************/
  466. /* read options from string 'str'                                             */
  467.  
  468. void ReadOptions(char *str, int *readKeyString, int *readKeyHexString)
  469.  
  470. {    char ch;
  471.  
  472.     str++;
  473.     *readKeyString = *readKeyHexString = FALSE;
  474.     while((ch = *(str++)) != 0) {
  475.         switch (ch) {
  476.             case 'a':
  477.                 if ((str[0] == 'b') && (str[1] == 'r'))
  478.                     SetMode(abr, &str);
  479.                 else
  480.                     UsageError(12);
  481.                 break;
  482.             case 'c':
  483.                 if ((str[0] == 'b') && (str[1] == 'c'))
  484.                     SetMode(cbc, &str);
  485.                 else if ((str[0] == 'f') && (str[1] == 'b'))
  486.                     SetMode(cfb, &str);
  487.                 else
  488.                     UsageError(13);
  489.                 break;
  490.             case 'd':
  491.                 SetOption(&optDecrypt);
  492.                 break;
  493.             case 'e': 
  494.                 if ((str[0] == 'c') && (str[1] == 'b'))
  495.                     SetMode(ecb, &str);
  496.                 else
  497.                     SetOption(&optEncrypt);
  498.                 break;
  499.             case 'h':
  500.                 SetOption(&optHash);
  501.                 break;
  502.             case 'H':
  503.                 SetOption(&optCopyHash);
  504.                 break;
  505.             case 'o':
  506.                 if ((str[0] == 'f') && (str[1] == 'b'))
  507.                     SetMode(ofb, &str);
  508.                 else
  509.                     UsageError(14);
  510.                 break;
  511.             case 'k':
  512.                 SetOption(&optKeyString);
  513.                 *readKeyString = TRUE;
  514.                 break;
  515.             case 'K':
  516.                 SetOption(&optKeyHexString);
  517.                 *readKeyHexString = TRUE;
  518.                 break;
  519.             case 't':
  520.                 if ((str[0] == 'a') && (str[1] == 'n'))
  521.                     SetMode(tan, &str);
  522.                 else
  523.                     UsageError(15);
  524.                 break;
  525.             default:
  526.                 UsageError(16);
  527.                 break;
  528.         }
  529.     }
  530.     if (*readKeyString && *readKeyHexString)
  531.         UsageError(17);
  532. } /* ReadOptions */
  533.  
  534. /******************************************************************************/
  535. /* check if options are unique and set default options                        */
  536.  
  537. void AdjustOptions()
  538.  
  539. {    if (optDecrypt && optEncrypt)
  540.         UsageError(18);
  541.     if (optHash && optCopyHash)
  542.         UsageError(19);
  543.     if (optKeyString && optKeyHexString)
  544.         UsageError(20);
  545.     if (optDecrypt || optEncrypt) {
  546.         if (optHash || optCopyHash)
  547.             UsageError(21);
  548.         if ((! optKeyString) && (! optKeyHexString))
  549.             UsageError(22);
  550.         if (mode == nomode) {
  551.             mode = cbc;
  552.             interleave = 1;
  553.         }
  554.         else if ((mode == tan) || (mode == abr))
  555.             UsageError(23);
  556.     }
  557.     else {
  558.         if (optHash || optCopyHash) {
  559.             if (mode == nomode)
  560.                 mode = tan;
  561.             else if ((mode != tan) && (mode != abr))
  562.                 UsageError(24);
  563.         }
  564.         else {
  565.             if (mode == nomode) {
  566.                 mode = cbc;
  567.                 interleave = 1;
  568.             }
  569.             if ((mode == tan) || (mode == abr))
  570.                 SetOption(&optHash);
  571.             else
  572.                 SetOption(&optEncrypt);
  573.         }
  574.     }
  575.     time = interleave;
  576.     time_N = 0;
  577. }    /* AdjustOptions */
  578.  
  579. /******************************************************************************/
  580. /* convert a hex-digit into an integer                                        */
  581.  
  582. int HexToInt(char ch)
  583.  
  584. {
  585.     if (('0' <= ch) && (ch <= '9'))
  586.         return ch - '0';
  587.     else if (('a' <= ch)  && (ch <= 'f'))
  588.         return 10 + (ch - 'a');
  589.     else if (('A' <= ch) && (ch <= 'F'))
  590.         return 10 + (ch - 'A');
  591.     else if (ch == ':')
  592.         return colon;
  593.     else if (ch == 0)
  594.         return eol;
  595.     else
  596.         return error;
  597. } /* HexToInt */
  598.  
  599. /******************************************************************************/
  600. /* convert a character into an integer                                        */
  601.  
  602. int32 CharToInt(char ch)
  603.  
  604. {
  605.     if (('!' <= ch) && (ch <= '~'))
  606.         return ch - '!';
  607.     else if (ch == 0)
  608.         return eol;
  609.     else
  610.         return error;
  611. } /* CharToInt */
  612.  
  613. /******************************************************************************/
  614. /* initializes key and initial values                                         */
  615.  
  616. void ReadKeyHexString(char *str)
  617.  
  618. {    int i, pos;
  619.     int32 h, val;
  620.  
  621.     while ((val = HexToInt(*(str++))) >= 0) {
  622.         for (i = userKeyLen - 1; i >= 0; i--) {
  623.             h = ((int32)(userKey[i]) >> 12) & 0xF;
  624.             userKey[i] = ((int32)(userKey[i]) << 4) | val;
  625.             val = h;
  626.         }
  627.         if (val != 0)
  628.             Error(25, "key value is too large");
  629.     }
  630.     pos = 0;
  631.     while ((val == colon) && (pos < maxInterleave)) {
  632.         val = HexToInt(*(str++));
  633.         while (val >= 0) {
  634.             for (i = dataLen - 1; i >= 0; i--) {
  635.                 h = ((int32)(state[pos][i]) >> 12) & 0xF;
  636.                 state[pos][i] = ((int32)(state[pos][i]) << 4) | val;
  637.                 val = h;
  638.             }
  639.             if (val != 0)
  640.                 Error(26, "initial value is too large");
  641.             val = HexToInt(*(str++));
  642.         }
  643.         pos++;
  644.     }
  645.     if (val == colon)
  646.         Error(27, "too many initial values specified");
  647.     if (val != eol)
  648.         Error(28, "wrong character in initialization string");
  649. } /* ReadKeyHexString */
  650.  
  651. /******************************************************************************/
  652. /* initialize key and initial values                                          */
  653.  
  654. void ReadKeyString(char *str)
  655.  
  656. {    int i;
  657.     int32 h, val;
  658.  
  659.     while ((val = CharToInt(*(str++))) >= 0) {
  660.         for (i = userKeyLen - 1; i >= 0; i--) {
  661.             h = (int32)(userKey[i]) * nofChar + val;
  662.             userKey[i] = h & 0xFFFF;
  663.             val = h >> 16;
  664.         }
  665.     }
  666. } /* ReadKeyString */
  667.  
  668.  
  669. /******************************************************************************/
  670. /*                          M A I N - P R O C E D U R E                       */
  671. /******************************************************************************/
  672. main(int argc, char *argv[])
  673.  
  674. {    int readKeyString, readKeyHexString;
  675.  
  676.     Init();
  677.     argv++; 
  678.     argc--;
  679.     if ((argc == 0) || (*(argv[0]) == '?'))
  680.         UsageError(0);
  681.     while ((argc > 0) && (*(argv[0]) == '-') && (*(argv[0]+1) != '\0')) {
  682.         ReadOptions(*argv++, &readKeyString, &readKeyHexString);
  683.         argc--;
  684.         if (readKeyString || readKeyHexString) {
  685.             if (argc <= 0)
  686.                 Error(29, "missing key on command line");
  687.             else if (readKeyString) {
  688.                 ReadKeyString(*(argv++));
  689.                 argc--;
  690.             }
  691.             else {
  692.                 ReadKeyHexString(*(argv++));
  693.                 argc--;
  694.             }
  695.         }
  696.     }
  697.     AdjustOptions();
  698.     if ((optCopyHash && (argc > 3)) || (! optCopyHash && (argc > 2)))
  699.         Error(30, "too many parameters");
  700.     if ((argc > 1) && (strcmp(argv[0], argv[1]) == 0))
  701.         Error(31, "source and destination are identical");
  702.     if ((argc > 2) && (strcmp(argv[0], argv[2]) == 0))
  703.         Error(32, "source and destination are identical");
  704.     if ((argc > 2) && (strcmp(argv[1], argv[2]) == 0))
  705.         Error(33, "destinations are identical");
  706.     inFile = stdin;
  707.     outFile = hashFile = stdout;
  708.     if (argc > 0) {
  709.         if (strcmp(*argv, "-") == 0) {
  710.             argv++;
  711.             argc--;
  712.         }
  713.         else {
  714.             inFile = fopen(*argv++, "r");
  715.             argc--;
  716.             if (inFile == 0)
  717.                 PError(*--argv);
  718.         }
  719.     }
  720.     if (optCopyHash) {
  721.         if (argc > 1) {
  722.             outFile = fopen(*argv++, "w");
  723.             argc--;
  724.             if (outFile == 0)
  725.                 PError(*--argv);
  726.         }
  727.         if (argc > 0) {
  728.             hashFile = fopen(*argv++, "w");
  729.             argc--;
  730.             if (hashFile == 0)
  731.             PError(*--argv);
  732.         }
  733.         else
  734.             hashFile = stderr;
  735.     }
  736.     else if (optHash) {
  737.         if (argc > 0) {
  738.             hashFile = fopen(*argv++, "w");
  739.             argc--;
  740.             if (hashFile == 0)
  741.                 PError(*--argv);
  742.         }
  743.     }
  744.     else {
  745.         if (argc > 0) {
  746.             outFile = fopen(*argv++, "w");
  747.             argc--;
  748.             if (outFile == 0)
  749.                 PError(*--argv);
  750.         }
  751.     }
  752.     if (argc > 0)
  753.         Error(34, "too many parameters");
  754.     ExpandUserKey(userKey, key);
  755.     if (optDecrypt && ((mode == ecb) || (mode == cbc)))
  756.         InvertIdeaKey(key, key);
  757.     CryptData();
  758.     exit(0);
  759. }
  760.